﻿#region zh-CHS 2006 - 2007 DemoSoft 团队 | en 2006 - 2007 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the G.O.S.E(Game Online Server Engine) for .NET.
//
//                 2006-2007 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using Demo_G.O.S.E.ServerEngine.Util;
using Demo_G.O.S.E.ServerEngine.Item;
using Demo_G.O.S.E.ServerEngine.Common;
#endregion

namespace Demo_G.O.S.E.ServerEngine.Creature
{
    /// <summary>
    /// 
    /// </summary>
    public class BaseBagManager
    {
        #region zh-CHS 共有属性 | en Public Properties

        #region zh-CHS Owner 属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private BaseCreature m_Owner = null;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public BaseCreature Owner
        {
            get { return m_Owner; }
            set { m_Owner = value; }
        }

        #endregion

        #region zh-CHS MinSlot属性 | en Public Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private long m_MinSlot = 0;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public long MinSlot
        {
            get { return m_MinSlot; }
        }

        #region zh-CHS 保护方法 | en Protected Methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="iMinSlot"></param>
        public void SetMinSlot( long iMinSlot )
        {
            m_MinSlot = iMinSlot;
        }

        #endregion

        #endregion

        #region zh-CHS MaxSlot属性 | en Public Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private long m_MaxSlot = long.MaxValue;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public long MaxSlot
        {
            get { return m_MaxSlot; }
        }

        #region zh-CHS 保护方法 | en Protected Methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="iMinSlot"></param>
        public void SetMaxSlot( long iMaxSlot )
        {
            m_MaxSlot = iMaxSlot;
        }

        #endregion

        #endregion

        #region zh-CHS IsContainerFull属性 | en Public Properties
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool IsContainerFull
        {
            get
            {
                if ( m_ToteContainers.Count < ( ( this.MaxSlot - this.MinSlot ) + 1 ) )
                    return false;
                else
                    return true;
            }
        }
        #endregion

        #region zh-CHS ItemContainer 属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 人物的道具列表
        /// </summary>
        private SafeDictionary<long, BaseItemContainer> m_ToteContainers = new SafeDictionary<long, BaseItemContainer>();
        #endregion
        /// <summary>
        /// 人物的道具列表(包裹与身上)
        /// </summary>
        /// <returns></returns>
        [MultiThreadedWarningAttribute( "(道具)当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public BaseItemContainer[] ToArray()
        {
            return m_ToteContainers.ToArray();
        }

        #region zh-CHS 共有方法 | en Public Methods

        /// <summary>
        /// 添加道具
        /// </summary>
        /// <param name="item"></param>
        public bool AddContainer( long iContainerSlot, BaseItemContainer baseItemContainer )
        {
            if ( baseItemContainer == null )
            {
                Debug.WriteLine( "BaseBagManager.AddContainer(...) - baseItemContainer == null error!" );

                return false;
            }

            if ( iContainerSlot > this.MaxSlot || iContainerSlot < this.MinSlot )
                return false;

            BaseItemContainer findItemContainer = FindContainerAtSlot( iContainerSlot );
            if ( findItemContainer != null )
            {
                Debug.WriteLine( "BaseBagManager.AddContainer(...) - findItemContainer != null error!" );

                return false;
            }

            EventHandler<BeforeAddItemContainerCallEventArgs> tempBeforeEventArgs = m_ThreadEventBeforeAddItemContainerCall;
            if ( tempBeforeEventArgs != null )
            {
                BeforeAddItemContainerCallEventArgs eventArgs = new BeforeAddItemContainerCallEventArgs( baseItemContainer, this );
                tempBeforeEventArgs( this, eventArgs );

                if ( eventArgs.IsCancel == true )
                    return false;
            }

            m_ToteContainers.Add( iContainerSlot, baseItemContainer );
            baseItemContainer.SetSlotId( iContainerSlot );

            EventHandler<AfterAddItemContainerCallEventArgs> tempAfterEventArgs = m_ThreadEventAfterAddItemContainerCall;
            if ( tempAfterEventArgs != null )
            {
                AfterAddItemContainerCallEventArgs eventArgs = new AfterAddItemContainerCallEventArgs( baseItemContainer, this );
                tempAfterEventArgs( this, eventArgs );
            }

            return true;
        }

        /// <summary>
        /// 移出道具
        /// </summary>
        /// <param name="item"></param>
        public bool RemoveContainer( long iContainerSlot )
        {
            if ( iContainerSlot > this.MaxSlot || iContainerSlot < this.MinSlot )
                return false;

            BaseItemContainer baseItemContainer = FindContainerAtSlot( iContainerSlot );
            if ( baseItemContainer == null )
                return false;

            EventHandler<BeforeRemoveItemContainerCallEventArgs> tempBeforeEventArgs = m_ThreadEventBeforeRemoveItemContainerCall;
            if ( tempBeforeEventArgs != null )
            {
                BeforeRemoveItemContainerCallEventArgs eventArgs = new BeforeRemoveItemContainerCallEventArgs( baseItemContainer, this );
                tempBeforeEventArgs( this, eventArgs );

                if ( eventArgs.IsCancel == true )
                    return false;
            }

            m_ToteContainers.Remove( iContainerSlot );
            baseItemContainer.SetSlotId( -1 );

            EventHandler<AfterRemoveItemContainerCallEventArgs> tempAfterEventArgs = m_ThreadEventAfterRemoveItemContainerCall;
            if ( tempAfterEventArgs != null )
            {
                AfterRemoveItemContainerCallEventArgs eventArgs = new AfterRemoveItemContainerCallEventArgs( baseItemContainer, this );
                tempAfterEventArgs( this, eventArgs );
            }

            return true;
        }

        /// <summary>
        /// 找道具
        /// </summary>
        /// <param name="layer"></param>
        /// <returns></returns>
        public BaseItemContainer FindContainerAtSlot( long iContainerSlot )
        {
            return m_ToteContainers.GetValue( iContainerSlot );
        }

        /// <summary>
        /// 
        /// </summary>
        public void EmptyBag()
        {
            m_ToteContainers.Clear();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        public bool AddToFreeContainerSlot( BaseItemContainer baseItemContainer )
        {
            long iRetrunItemContainerSlot = -1;
            if ( this.FindFreeContainerSlot( ref iRetrunItemContainerSlot ) == false )
                return false;

            if ( this.AddContainer( iRetrunItemContainerSlot, baseItemContainer ) == false )
                return false;

            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="layer"></param>
        /// <returns></returns>
        public bool FindFreeContainerSlot( ref long iRetrunItemContainerSlot )
        {
            iRetrunItemContainerSlot = -1;

            if ( this.IsContainerFull == true )
                return false;

            for ( long iIndexSlot = this.MinSlot; iIndexSlot <= this.MaxSlot; iIndexSlot++ )
            {
                BaseItemContainer baseItemContainer = FindContainerAtSlot( iIndexSlot );

                if ( baseItemContainer == null )
                {
                    iRetrunItemContainerSlot = iIndexSlot;
                    return true;
                }
            }

            return false;
        }
        #endregion

        #endregion

        #endregion

        #region zh-CHS 共有方法 | en Public Methods
        /// <summary>
        /// 
        /// </summary>
        /// <param name="wowItem"></param>
        /// <returns></returns>
        public BaseItemContainer FindSpecialBag( BaseItem baseItem )
        {
            if ( baseItem == null )
                return null;

            BaseItemContainer[] baseItemContainerArray = this.ToArray();
            if ( baseItemContainerArray == null )
                return null;

            foreach ( BaseItemContainer baseItemContainer in baseItemContainerArray )
            {
                BaseItem[] baseItemArray = baseItemContainer.SubItemsToArray();
                if ( baseItemContainerArray == null )
                    continue;

                foreach ( BaseItem item in baseItemArray )
                {
                    if ( item.Serial == baseItem.Serial )
                        return baseItemContainer;
                }
            }

            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="layer"></param>
        /// <returns></returns>
        public BaseItem FindSubItemAtContainerSlot( long iContainerSlot, long iItemSlot )
        {
            BaseItemContainer baseItemContainer = FindContainerAtSlot( iContainerSlot );
            if ( baseItemContainer == null )
                return null;

            return baseItemContainer.FindSubItemAtSlot( iItemSlot );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseItem"></param>
        /// <returns></returns>
        public bool AddSubItemToFreeContainer( BaseItem baseItem )
        {
            BaseItemContainer[] baseItemContainerArray = this.ToArray();
            if ( baseItemContainerArray == null )
                return false;

            foreach ( BaseItemContainer baseItemContainer in baseItemContainerArray )
            {
                if ( baseItemContainer.AddToFreeSlot( baseItem ) == true )
                    return true;
            }

            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="iContainerSlotForm"></param>
        /// <param name="iItemSlotForm"></param>
        /// <param name="iContainerSlotTo"></param>
        /// <returns></returns>
        public bool MoveSubItemToSpecialContainer( long iContainerSlotForm, long iItemSlotForm, long iContainerSlotTo )
        {
            BaseItemContainer baseItemContainerForm = FindContainerAtSlot( iContainerSlotForm );
            if ( baseItemContainerForm == null )
                return false;

            BaseItem baseItemForm = baseItemContainerForm.FindSubItemAtSlot( iItemSlotForm );
            if ( baseItemForm == null )
                return false;

            BaseItemContainer baseItemContainerTo = FindContainerAtSlot( iContainerSlotTo );
            if ( baseItemContainerTo == null )
                return false;

            long iRetrunItemSlot = -1;
            if ( baseItemContainerTo.FindFreeSlot( ref iRetrunItemSlot ) == false )
                return false;

            if ( baseItemContainerForm.RemoveSubItem( iItemSlotForm ) == false )
                return false;

            if ( baseItemContainerTo.AddSubItem( iRetrunItemSlot, baseItemForm ) == false )
            {
                if ( baseItemContainerForm.AddToFreeSlot( baseItemForm ) == false )
                {
                    Debug.WriteLine( "BaseBagManager.MoveItem(...) - baseItemContainerForm.AddToFreeSlot(...) error(No Complete, Lost baseItemForm)!" );
                    return false;
                }

                return false;
            }
            else
                return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="iContainerSlotForm"></param>
        /// <param name="iItemSlotForm"></param>
        /// <param name="iContainerSlotTo"></param>
        /// <param name="iItemSlotTo"></param>
        /// <returns></returns>
        public bool SwapSubItem( long iContainerSlotForm, long iItemSlotForm, long iContainerSlotTo, long iItemSlotTo )
        {
            BaseItemContainer baseItemContainerForm = FindContainerAtSlot( iContainerSlotForm );
            if ( baseItemContainerForm == null )
                return false;

            BaseItem baseItemForm = baseItemContainerForm.FindSubItemAtSlot( iItemSlotForm );
            if ( baseItemForm == null )
                return false;

            BaseItemContainer baseItemContainerTo = FindContainerAtSlot( iContainerSlotTo );
            if ( baseItemContainerTo == null )
                return false;

            BaseItem baseItemTo = baseItemContainerTo.FindSubItemAtSlot( iItemSlotTo );
            if ( baseItemTo == null )
                return false;

            if ( baseItemContainerForm.RemoveSubItem( iItemSlotForm ) == false )
                return false;

            if ( baseItemContainerTo.RemoveSubItem( iItemSlotTo ) == false )
            {
                if ( baseItemContainerForm.AddSubItem( iItemSlotForm, baseItemForm ) == false )
                    Debug.WriteLine( "BaseBagManager.SwapItem(...) - baseItemContainerForm.AddSubItem(.1.) error(No Complete, Lost baseItemForm)!" );

                return false;
            }

            if ( baseItemContainerForm.AddSubItem( iItemSlotForm, baseItemTo ) == false )
            {
                if ( baseItemContainerForm.AddSubItem( iItemSlotForm, baseItemForm ) == false )
                    Debug.WriteLine( "BaseBagManager.SwapItem(...) - baseItemContainerForm.AddSubItem(.2.) error(No Complete, Lost baseItemForm)!" );

                if ( baseItemContainerTo.AddSubItem( iItemSlotTo, baseItemTo ) == false )
                    Debug.WriteLine( "BaseBagManager.SwapItem(...) - baseItemContainerTo.AddSubItem(.1.) error(No Complete, Lost baseItemTo)!" );

                return false;
            }

            if ( baseItemContainerTo.AddSubItem( iItemSlotTo, baseItemForm ) == false )
            {
                if ( baseItemContainerForm.RemoveSubItem( iItemSlotForm ) == false )
                    Debug.WriteLine( "BaseBagManager.SwapItem(...) - baseItemContainerForm.RemoveSubItem(...) error!" );
                else
                {
                    // 恢复到原来
                    if ( baseItemContainerForm.AddSubItem( iItemSlotForm, baseItemForm ) == false )
                        Debug.WriteLine( "BaseBagManager.SwapItem(...) - baseItemContainerForm.AddSubItem(.3.) error(No Complete, Lost baseItemForm)!" );
                }

                if ( baseItemContainerTo.AddSubItem( iItemSlotTo, baseItemTo ) == false )
                    Debug.WriteLine( "BaseBagManager.SwapItem(...) - baseItemContainerTo.AddSubItem(.2.) error(No Complete, Lost baseItemTo)!" );

                return false;
            }

            return true;
        }

        #endregion

        #region zh-CHS 共有事件 | en Public Event

        #region zh-CHS AddItemContainerCall事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<BeforeAddItemContainerCallEventArgs> m_ThreadEventBeforeAddItemContainerCall;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventBeforeAddItemContainerCall = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<BeforeAddItemContainerCallEventArgs> ThreadBeforeAddItemContainerCall
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventBeforeAddItemContainerCall );
                {
                    m_ThreadEventBeforeAddItemContainerCall += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventBeforeAddItemContainerCall );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventBeforeAddItemContainerCall );
                {
                    m_ThreadEventBeforeAddItemContainerCall -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventBeforeAddItemContainerCall );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<AfterAddItemContainerCallEventArgs> m_ThreadEventAfterAddItemContainerCall;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventAfterAddItemContainerCall = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<AfterAddItemContainerCallEventArgs> ThreadAfterAddItemContainerCall
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventAfterAddItemContainerCall );
                {
                    m_ThreadEventAfterAddItemContainerCall += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventAfterAddItemContainerCall );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventAfterAddItemContainerCall );
                {
                    m_ThreadEventAfterAddItemContainerCall -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventAfterAddItemContainerCall );
            }
        }
        #endregion

        #region zh-CHS RemoveItemContainerCall事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<BeforeRemoveItemContainerCallEventArgs> m_ThreadEventBeforeRemoveItemContainerCall;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventBeforeRemoveItemContainerCall = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<BeforeRemoveItemContainerCallEventArgs> ThreadBeforeRemoveItemContainerCall
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventBeforeRemoveItemContainerCall );
                {
                    m_ThreadEventBeforeRemoveItemContainerCall += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventBeforeRemoveItemContainerCall );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventBeforeRemoveItemContainerCall );
                {
                    m_ThreadEventBeforeRemoveItemContainerCall -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventBeforeRemoveItemContainerCall );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<AfterRemoveItemContainerCallEventArgs> m_ThreadEventAfterRemoveItemContainerCall;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockThreadEventAfterRemoveItemContainerCall = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<AfterRemoveItemContainerCallEventArgs> ThreadAfterRemoveItemContainerCall
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventAfterRemoveItemContainerCall );
                {
                    m_ThreadEventAfterRemoveItemContainerCall += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventAfterRemoveItemContainerCall );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockThreadEventAfterRemoveItemContainerCall );
                {
                    m_ThreadEventAfterRemoveItemContainerCall -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockThreadEventAfterRemoveItemContainerCall );
            }
        }
        #endregion

        #endregion
    }
}
#endregion